package pointor

import (
	"fmt"
	"unsafe"
)


// 不同类型指针的转化
func Intp2floatp(){
	/**
	任何类型的指针值都可以转换为 Pointer。
	Pointer 可以转换为任何类型的指针值。
	uintptr 可以转换为 Pointer。
	Pointer 可以转换为 uintptr。
	 */


	num := 5
	numPointer := &num

	flnum := (*float32)(unsafe.Pointer(numPointer))
	fmt.Println(*flnum)
}



type Num struct{
	i string
	j int64
}





/**

*T：普通类型指针类型，用于传递对象地址，不能进行指针运算。
unsafe.poniter：通用指针类型，用于转换不同类型的指针，不能进行指针运算，不能读取内存存储的值(需转换到某一类型的普通指针)
uintptr：用于指针运算，GC不把uintptr当指针，uintptr无法持有对象。uintptr类型的目标会被回收。

 */

//结构体成员的偏移
func StructOffset(){

	n := Num{i: "EDDYCJY", j: 1}


	/**
	Sizeof(x ArbitrayType)方法主要作用是用返回类型x所占据的字节数，但并不包含x所指向的内容的大小，
	与C语言标准库中的Sizeof()方法功能一样，比如在32位机器上，一个指针返回大小就是4字节。
	 */
	fmt.Println("----------------",unsafe.Sizeof(n))

	/**
	Pointer指针类型，即像void *一样的通用型指针
	 */
	nPointer := unsafe.Pointer(&n)

	niPointer := (*string)(unsafe.Pointer(nPointer))
	*niPointer = "煎鱼"


	/**
	Offsetof(x ArbitraryType)方法主要作用是
	返回结构体成员在内存中的位置离结构体起始处(结构体的第一个字段的偏移量都是0)的字节数，即偏移量，
	我们在注释中看一看到其入参必须是一个结构体，其返回值是一个常量。
	 */
	njPointer := (*int64)(unsafe.Pointer(uintptr(nPointer) + unsafe.Offsetof(n.j)))
	*njPointer = 2

	fmt.Printf("n.i: %s, n.j: %d", n.i, n.j)
}

